package com.miplus.ccrm.workflow.js;

import com.alibaba.fastjson.JSONObject;
import com.miplus.ccrm.workflow.logic.LfEdge;
import com.miplus.ccrm.workflow.logic.LfNode;
import com.miplus.ccrm.workflow.logic.LogicFlow;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 将LogicFlow转换为可执行的JavaScript代码
 */
public class LogicFlowToJSConverter {
    
    /**
     * 将LogicFlow对象转换为可执行的JavaScript代码
     * @param logicFlow LogicFlow对象
     * @return 可执行的JavaScript代码
     */
    public static String convertToJS(LogicFlow logicFlow) {
        StringBuilder jsCode = new StringBuilder();
        
        // 添加函数定义头部
        jsCode.append("// LogicFlow自动生成的可执行代码\n");
        jsCode.append("async function executeWorkflow() {\n");
        jsCode.append("  // 定义变量\n");
        jsCode.append("  const context = {};\n");
        jsCode.append("  const results = {};\n\n");
        
        // 获取执行顺序
        List<String> executionOrder = getExecutionOrder(logicFlow);
        
        // 生成节点执行代码
        for (String nodeId : executionOrder) {
            // 查找对应节点
            LfNode node = logicFlow.getNodes().stream()
                    .filter(n -> n.getId().equals(nodeId))
                    .findFirst()
                    .orElse(null);
            
            if (node != null) {
                jsCode.append(generateNodeExecutionCode(node, logicFlow));
            }
        }
        
        // 添加返回语句
        jsCode.append("  \n  return context;\n");
        jsCode.append("}\n\n");
        
        // 添加辅助函数定义
        jsCode.append("// 辅助函数定义\n");
        jsCode.append("async function executeNode(nodeId, nodeType, properties) {\n");
        jsCode.append("  console.log(`Executing node ${nodeId} of type ${nodeType}`);\n");
        jsCode.append("  // 这里应该根据节点类型执行相应的逻辑\n");
        jsCode.append("  // 例如调用API、处理数据等\n");
        jsCode.append("  return { nodeId, nodeType, status: 'completed' };\n");
        jsCode.append("}\n\n");
        
        jsCode.append("async function callAIModel(context) {\n");
        jsCode.append("  console.log('Calling AI model with context:', context);\n");
        jsCode.append("  // 模拟AI模型调用\n");
        jsCode.append("  return 'AI generated response based on context';\n");
        jsCode.append("}\n\n");
        
        jsCode.append("async function generateReply(context) {\n");
        jsCode.append("  console.log('Generating reply with context:', context);\n");
        jsCode.append("  // 根据上下文生成回复\n");
        jsCode.append("  return context.aiResponse || 'Default reply';\n");
        jsCode.append("}\n\n");
        
        jsCode.append("async function makeHttpRequest(context) {\n");
        jsCode.append("  console.log('Making HTTP request with context:', context);\n");
        jsCode.append("  // 模拟HTTP请求\n");
        jsCode.append("  return { status: 200, data: 'Response data' };\n");
        jsCode.append("}\n\n");
        
        jsCode.append("function evaluateCondition(context) {\n");
        jsCode.append("  console.log('Evaluating condition with context:', context);\n");
        jsCode.append("  // 模拟条件评估\n");
        jsCode.append("  return true;\n");
        jsCode.append("}\n\n");
        
        // 添加自动执行
        jsCode.append("// 自动执行工作流\n");
        jsCode.append("executeWorkflow().then(result => {\n");
        jsCode.append("  console.log('Workflow execution completed:', result);\n");
        jsCode.append("}).catch(error => {\n");
        jsCode.append("  console.error('Workflow execution failed:', error);\n");
        jsCode.append("});\n");
        
        return jsCode.toString();
    }
    
    /**
     * 根据节点依赖关系确定执行顺序（拓扑排序）
     * @param logicFlow LogicFlow对象
     * @return 节点执行顺序列表
     */
    private static List<String> getExecutionOrder(LogicFlow logicFlow) {
        // 构建图的邻接表表示
        Map<String, List<String>> graph = new HashMap<>();
        Map<String, Integer> inDegree = new HashMap<>();
        
        // 初始化所有节点
        for (LfNode node : logicFlow.getNodes()) {
            String nodeId = node.getId();
            graph.putIfAbsent(nodeId, new ArrayList<>());
            inDegree.putIfAbsent(nodeId, 0);
        }
        
        // 构建边关系和入度
        for (LfEdge edge : logicFlow.getEdges()) {
            String source = edge.getSourceNodeId();
            String target = edge.getTargetNodeId();
            
            // 添加边
            graph.get(source).add(target);
            // 增加目标节点的入度
            inDegree.put(target, inDegree.get(target) + 1);
        }
        
        // 拓扑排序（Kahn算法）
        Queue<String> queue = new LinkedList<>();
        List<String> result = new ArrayList<>();
        
        // 将所有入度为0的节点加入队列
        for (Map.Entry<String, Integer> entry : inDegree.entrySet()) {
            if (entry.getValue() == 0) {
                queue.offer(entry.getKey());
            }
        }
        
        // 处理队列中的节点
        while (!queue.isEmpty()) {
            String node = queue.poll();
            result.add(node);
            
            // 遍历当前节点的所有邻居
            for (String neighbor : graph.get(node)) {
                // 减少邻居节点的入度
                inDegree.put(neighbor, inDegree.get(neighbor) - 1);
                // 如果邻居节点的入度变为0，则加入队列
                if (inDegree.get(neighbor) == 0) {
                    queue.offer(neighbor);
                }
            }
        }
        
        return result;
    }
    
    /**
     * 生成单个节点的执行代码
     * @param node 节点对象
     * @param logicFlow LogicFlow对象
     * @return JavaScript代码片段
     */
    private static String generateNodeExecutionCode(LfNode node, LogicFlow logicFlow) {
        StringBuilder code = new StringBuilder();
        
        String nodeId = node.getId();
        String nodeType = node.getType();
        
        code.append(String.format("  // 执行节点: %s (%s)\n", nodeId, nodeType));
        code.append(String.format("  console.log('Executing node: %s');\n", nodeId));
        
        // 根据节点类型生成不同的执行代码
        switch (nodeType) {
            case "start-node":
                code.append(generateStartNodeCode(node));
                break;
            case "ai-chat-node":
                code.append(generateAIChatNodeCode(node));
                break;
            case "reply-node":
                code.append(generateReplyNodeCode(node));
                break;
            case "condition-node":
                code.append(generateConditionNodeCode(node, logicFlow));
                break;
            case "http-client-node":
                code.append(generateHttpClientNodeCode(node));
                break;
            default:
                code.append(String.format("  await executeNode('%s', '%s', %s);\n", 
                    nodeId, nodeType, node.getProperties() != null ? node.getProperties().toJSONString() : "{}"));
                break;
        }
        
        code.append("\n");
        return code.toString();
    }
    
    /**
     * 生成开始节点代码
     * @param node 节点对象
     * @return JavaScript代码片段
     */
    private static String generateStartNodeCode(LfNode node) {
        StringBuilder code = new StringBuilder();
        code.append("  context.startTime = new Date().toISOString();\n");
        code.append("  context.initialized = true;\n");
        code.append("  context.question = '用户问题示例';\n");
        return code.toString();
    }
    
    /**
     * 生成AI聊天节点代码
     * @param node 节点对象
     * @return JavaScript代码片段
     */
    private static String generateAIChatNodeCode(LfNode node) {
        StringBuilder code = new StringBuilder();
        code.append("  const aiResponse = await callAIModel(context);\n");
        code.append("  context.aiResponse = aiResponse;\n");
        code.append("  results['").append(node.getId()).append("'] = aiResponse;\n");
        return code.toString();
    }
    
    /**
     * 生成回复节点代码
     * @param node 节点对象
     * @return JavaScript代码片段
     */
    private static String generateReplyNodeCode(LfNode node) {
        StringBuilder code = new StringBuilder();
        code.append("  const replyContent = await generateReply(context);\n");
        code.append("  context.reply = replyContent;\n");
        code.append("  console.log('Reply:', replyContent);\n");
        return code.toString();
    }
    
    /**
     * 生成条件节点代码
     * @param node 节点对象
     * @param logicFlow LogicFlow对象
     * @return JavaScript代码片段
     */
    private static String generateConditionNodeCode(LfNode node, LogicFlow logicFlow) {
        StringBuilder code = new StringBuilder();
        
        // 查找从该条件节点出发的边
        List<LfEdge> outgoingEdges = logicFlow.getEdges().stream()
                .filter(edge -> edge.getSourceNodeId().equals(node.getId()))
                .collect(Collectors.toList());
        
        code.append("  const conditionResult = evaluateCondition(context);\n");
        code.append("  context.conditionResult = conditionResult;\n");
        code.append("  results['").append(node.getId()).append("'] = conditionResult;\n");
        
        // 为每个分支生成代码
        for (LfEdge edge : outgoingEdges) {
            String targetNodeId = edge.getTargetNodeId();
            String sourceAnchorId = edge.getSourceAnchorId();
            
            // 解析锚点ID以确定分支
            if (sourceAnchorId != null && sourceAnchorId.contains("_")) {
                String[] parts = sourceAnchorId.split("_");
                if (parts.length >= 3) {
                    String branchId = parts[parts.length - 2]; // 倒数第二个是分支ID
                    code.append(String.format("  // 分支 %s 指向节点 %s\n", branchId, targetNodeId));
                }
            }
        }
        
        return code.toString();
    }
    
    /**
     * 生成HTTP客户端节点代码
     * @param node 节点对象
     * @return JavaScript代码片段
     */
    private static String generateHttpClientNodeCode(LfNode node) {
        StringBuilder code = new StringBuilder();
        code.append("  const httpResponse = await makeHttpRequest(context);\n");
        code.append("  context.httpResponse = httpResponse;\n");
        code.append("  results['").append(node.getId()).append("'] = httpResponse;\n");
        return code.toString();
    }
    
    /**
     * 从JSON对象转换为JavaScript代码
     * @param logicFlowJson LogicFlow的JSON表示
     * @return 可执行的JavaScript代码
     */
    public static String convertToJS(JSONObject logicFlowJson) {
        LogicFlow logicFlow = LogicFlow.newInstance(logicFlowJson);
        return convertToJS(logicFlow);
    }
}